/* eslint-disable import/no-cycle */
import { getItemForPk, getProductNameFromConfig, isBLE, isSupportBLEControl } from '@/config/product';
import { deviceIsBleConnect, getDeviceId, deviceIsBleBroadCast } from '@/utils';
import language from '../language';

// 默认通信协议优先级，蓝牙优先于WiFi
const defaultM2mProtocSort = ['BLE', 'WIFI']; // 其实m2mProtoc类别很多，这里暂定没有指明是BLE的，都是WiFi

// 能力的状态，这里的值一定要按优先级排列，可控是最高级别
export enum CapacityState {
  offline = 0, // 离线不可用
  online = 1, // 在线
  inPreparation = 2, // 准备中，主要用于wifi状态的订阅
  connecting = 3, // 连接中，用于记录蓝牙连接与断开，有这状态，代表是用户手动的选择
  controllable = 4, // 可控制的
}

// 能力名字，暂时划分为Wifi和Ble，枚举值与m2mProtoc值一直，方便比较
export enum DeviceCapacityName {
  ble = 'BLE',
  wifi = 'WIFI',
}

export enum ConnectState {
  connecting = -1,
  disconnecting = -2,
}

export interface IConnectStateMap {
  [deviceId: string]: ConnectState;
}

export interface IDeviceCapacity {
  name: DeviceCapacityName; // 能力的名字
  state: CapacityState; // 能力状态
  netStatus: number; // 保存原本的sdk返回的状态
  level: number; // 能力优先级
}

class DeviceCapacity implements IDeviceCapacity {
  name: DeviceCapacityName; // 能力的名字
  state: CapacityState; // 能力状态
  netStatus: number; // 状态
  level: number; // 能力优先级，默认0
  constructor(props: IDeviceCapacity) {
    this.name = props.name;
    this.state = props.state;
    this.netStatus = props.netStatus;
    this.level = props.level;
  }
}

function getBleDefaultCapacity() {
  return new DeviceCapacity({ name: DeviceCapacityName.ble, state: CapacityState.offline, netStatus: 0, level: 0 });
}

function getWifiDefaultCapacity() {
  return new DeviceCapacity({ name: DeviceCapacityName.wifi, state: CapacityState.offline, netStatus: 0, level: 0 });
}

// 获取能力的netStatus，没有就是-1
function getCapacityNetstatus(capacity?: DeviceCapacity) {
  if (capacity) {
    return capacity.netStatus;
  }
  return -1;
}

// 根据通讯协议优先级配置获取能力的优先级
function getCapacityLevelByM2mProtocSort({
  m2mProtocSort = defaultM2mProtocSort,
  capacity,
}: {
  m2mProtocSort?: string[];
  capacity: DeviceCapacity;
}) {
  const index = m2mProtocSort.findIndex(i => i === capacity.name);
  if (index > -1) {
    // 排在越前面优先级越高
    return m2mProtocSort.length - 1 - index;
  }
  return 0;
}

// 排序能力要先显示哪个
export function sortCapacityUse(a: IDeviceCapacity, b: IDeviceCapacity) {
  // 状态值更大，证明越接近可用
  if (a.state !== b.state) {
    return a.state > b.state ? -1 : 1;
  }
  if (a.level !== b.level) {
    return a.level > b.level ? -1 : 1;
  }
  return 0;
}

export interface INewDevice extends IDevice {
  productName?: string; // 产品名字
  wifiCapacity?: DeviceCapacity; // wifi能力
  bleCapacity?: DeviceCapacity; // 蓝牙能力
}

// 根据记录的蓝牙连接与断开连接状态，更新能力
export function updateDeviceBybleConnectStateMap({
  device,
  bleConnectStateMap,
}: {
  device: INewDevice;
  bleConnectStateMap: IConnectStateMap;
}) {
  // 更新蓝牙连接状态
  const connectState = bleConnectStateMap[device.deviceId];
  if (connectState) {
    switch (connectState) {
      case ConnectState.connecting:
        if (device.bleCapacity) {
          // eslint-disable-next-line no-param-reassign
          device.bleCapacity.state = CapacityState.connecting;
        }
        break;
      case ConnectState.disconnecting:
        // 蓝牙断开连接，那就代表是正在切换成wifi，wifi能力变成连接中
        if (device.wifiCapacity) {
          // eslint-disable-next-line no-param-reassign
          device.wifiCapacity.state = CapacityState.connecting;
        }
        break;
      default:
        break;
    }
  }
}

// 根据蓝牙能力的netStatus更新能力的satte
export function updateBleCapacityState(bleCapacity: IDeviceCapacity) {
  if (bleCapacity.netStatus === 2) {
    // eslint-disable-next-line no-param-reassign
    bleCapacity.state = CapacityState.controllable;
  } else if (bleCapacity.netStatus === 1) {
    // eslint-disable-next-line no-param-reassign
    bleCapacity.state = CapacityState.online;
  } else {
    // eslint-disable-next-line no-param-reassign
    bleCapacity.state = CapacityState.offline;
  }
}

// 根据Wifi能力的netStatus更新能力的satte
export function updateWifiCapacityState(wifiCapacity: IDeviceCapacity) {
  switch (wifiCapacity.netStatus) {
    case 0:
      // eslint-disable-next-line no-param-reassign
      wifiCapacity.state = CapacityState.offline;
      break;
    case 1:
      // 代表是在线，但由于wifi是自动订阅的，所以不直接在线，而是准备中
      // eslint-disable-next-line no-param-reassign
      wifiCapacity.state = CapacityState.inPreparation;
      break;
    case 2:
      // eslint-disable-next-line no-param-reassign
      wifiCapacity.state = CapacityState.controllable;
      break;
    default:
      break;
  }
}

/**
 * 计算设备能力方法
 * 返回一个INewDevice
 * 蓝牙可控状态优先于wifi可控
 * 设备对象外层的netStatus按能力的合并计算，有一个能力是可控就可控，有一个能力是在线就在线
 */
export function getDeviceCapacities({
  wifiDevice,
  bleDevice,
  bleConnectStateMap,
}: {
  wifiDevice?: IDevice;
  bleDevice?: IDevice;
  bleConnectStateMap: IConnectStateMap;
}) {
  // console.log("getDeviceCapacities", wifiDevice, bleDevice);
  const sourceDevice = wifiDevice || bleDevice;
  if (sourceDevice) {
    const productConfig = getItemForPk(sourceDevice.productKey);
    if (productConfig) {
      const device: INewDevice = {
        ...sourceDevice,
        productName: getProductNameFromConfig(language.key, productConfig),
        deviceId: getDeviceId(sourceDevice),
        isSupportBlue: false,
        isBlueLocal: false,
      }; // 先复制一份

      // 是支持蓝牙控制的
      if (isSupportBLEControl(productConfig)) {
        const bleCapacity = getBleDefaultCapacity();
        bleCapacity.level = getCapacityLevelByM2mProtocSort({
          capacity: bleCapacity,
          m2mProtocSort: productConfig.m2mProtocSort,
        });
        device.isSupportBlue = sourceDevice.isBleOnline;
        let bleNetStatus = sourceDevice.isBleOnline ? 1 : 0;
        if (deviceIsBleConnect(sourceDevice)) {
          bleNetStatus = 2;
        } else if (deviceIsBleBroadCast(sourceDevice)) {
          bleNetStatus = 2;
        }
        bleCapacity.netStatus = bleNetStatus;
        updateBleCapacityState(bleCapacity);
        device.isBlueLocal = bleCapacity.netStatus === 2;

        // if (bleDevice) {
        //   // 有蓝牙设备才更新蓝牙能力状态
        //   device.isSupportBlue = true; // 兼容旧版属性
        //   bleCapacity.netStatus = bleDevice.netStatus;
        //   updateBleCapacityState(bleCapacity);
        //   device.isBlueLocal = bleCapacity.netStatus === 2;
        // }

        device.bleCapacity = bleCapacity;
      }
      // 支持wifi控制的
      if (!isBLE(productConfig)) {
        const wifiCapacity = getWifiDefaultCapacity();
        wifiCapacity.level = getCapacityLevelByM2mProtocSort({
          capacity: wifiCapacity,
          m2mProtocSort: productConfig.m2mProtocSort,
        });
        let wifiNetStatus = sourceDevice.isOnline ? 1 : 0;
        if (sourceDevice.isSubscribed && sourceDevice.isOnline) {
          wifiNetStatus = 2;
        }
        wifiCapacity.netStatus = wifiNetStatus;
        updateWifiCapacityState(wifiCapacity);

        // if (wifiDevice) {
        //   wifiCapacity.netStatus = wifiDevice.netStatus;
        //   updateWifiCapacityState(wifiCapacity);
        // }
        device.wifiCapacity = wifiCapacity;
      }
      // 能力计算
      // 计算最外层device的状态，0保底是离线
      device.netStatus = Math.max(
        0,
        getCapacityNetstatus(device.bleCapacity),
        getCapacityNetstatus(device.wifiCapacity)
      );
      device.isOnline = device.netStatus !== 0;

      // 更新蓝牙连接状态
      updateDeviceBybleConnectStateMap({ device, bleConnectStateMap });
      // console.log('getDeviceCapacities', device);
      return device;
    }
  }
  return undefined;
}

// 能力是否发生变化
function isCapacityChange(capacityA?: IDeviceCapacity, capacityB?: IDeviceCapacity) {
  if ((capacityA === undefined && capacityB !== undefined) || (capacityA !== undefined && capacityB === undefined)) {
    return true;
  }
  if (capacityA && capacityB) {
    if (capacityA.netStatus !== capacityB.netStatus || capacityA.state !== capacityB.state) {
      return true;
    }
  }
  return false;
}

// 设备能力是否发生变化
export function isDeviceCapacityChange(deviceA: INewDevice, deviceB: INewDevice) {
  if (
    deviceA.netStatus !== deviceB.netStatus ||
    deviceA.isBlueLocal !== deviceB.isBlueLocal ||
    deviceA.isSupportBlue !== deviceB.isSupportBlue
  ) {
    return true;
  }
  if (isCapacityChange(deviceA.wifiCapacity, deviceB.wifiCapacity)) {
    return true;
  }
  if (isCapacityChange(deviceA.bleCapacity, deviceB.bleCapacity)) {
    return true;
  }
  return false;
}

export function deviceIsInConnecting(device: INewDevice) {
  return (
    (device.bleCapacity && device.bleCapacity.state === CapacityState.connecting) ||
    (device.wifiCapacity && device.wifiCapacity.state === CapacityState.connecting)
  );
}

export default DeviceCapacity;
